#include "vdma_display.h"
#include "xil_cache.h"   // 包含 Xil_DCacheFlushRange 的声明
#include "xil_printf.h"  // 包含 xil_printf
#include <string.h>       // 包含 memset
#include "sleep.h"        // 添加 sleep 头文件
#include "font.h"


// 内部函数：刷新数据缓存
static int VdmaDisplay_flushCache(UINTPTR buffer_addr, u32 size_bytes) {
    Xil_DCacheFlushRange((INTPTR)buffer_addr, size_bytes);
    return XST_SUCCESS;
}

// 内部函数：使数据缓存失效
static int VdmaDisplay_invalidateCache(UINTPTR buffer_addr, u32 size_bytes) {
    Xil_DCacheInvalidateRange((INTPTR)buffer_addr, size_bytes);
    return XST_SUCCESS;
}

// VdmaDisplay 结构体的初始化函数
void VdmaDisplay_init_struct(VdmaDisplay* self) {
    int i;
    for (i = 0; i < VDMA_NUM_FRAME_BUFFERS; ++i) {
        self->hlsFrameBufferBaseAddr_[i] = 0;
        self->vdmaFrameBufferBaseAddr_[i] = 0;
    }
    self->vdmaConfig_ = NULL;
    self->nextHlsWriteBufferIdx_ = 0;
    self->currentDisplayBufferIdx_ = 0;
    self->initialized_ = false;
    memset(&self->vdmaDmaSetup_, 0, sizeof(XAxiVdma_DmaSetup));

    // 初始化新的信号量和互斥量
    self->xRenderingBufferAvailableSemaphore_ = NULL;
    self->xDisplayBufferCommitMutex_ = NULL;
}

// VDMA 初始化
int VdmaDisplay_init(VdmaDisplay* self) {
    int status;
    int i;

    if (self->initialized_) {
        xil_printf("Warning: VDMA display already initialized.\r\n");
        return XST_SUCCESS;
    }

    // --- 创建 FreeRTOS 同步对象 ---
    // 渲染缓冲区可用信号量：允许 VDMA_NUM_FRAME_BUFFERS - 1 个帧进行渲染
    // 最大计数设置为 VDMA_NUM_FRAME_BUFFERS - 1，初始计数也是 VDMA_NUM_FRAME_BUFFERS - 1
    // 因为有一个缓冲区被 VDMA 占用进行显示，其余 N-1 个可用于预渲染。
    self->xRenderingBufferAvailableSemaphore_ = xSemaphoreCreateCounting(VDMA_NUM_FRAME_BUFFERS - 1, VDMA_NUM_FRAME_BUFFERS - 1);
    if (self->xRenderingBufferAvailableSemaphore_ == NULL) {
        xil_printf("Error: Failed to create xRenderingBufferAvailableSemaphore_.\r\n");
        return XST_FAILURE;
    }
    // 显示缓冲区提交互斥量：确保对 VDMA 停车/提交操作的互斥访问
    self->xDisplayBufferCommitMutex_ = xSemaphoreCreateMutex();
    if (self->xDisplayBufferCommitMutex_ == NULL) {
        xil_printf("Error: Failed to create xDisplayBufferCommitMutex_.\r\n");
        // 如果互斥量创建失败，销毁已创建的信号量 (FreeRTOS没有直接的销毁函数，所以通常是崩溃或打印错误)
        return XST_FAILURE;
    }
    xil_printf("  FreeRTOS Semaphores created successfully.\r\n");

    // 计算并设置 HLS 和 VDMA 两套帧缓冲区的基地址
    for (i = 0; i < VDMA_NUM_FRAME_BUFFERS; ++i) {
        self->hlsFrameBufferBaseAddr_[i] = HLS_FRAME_BUFFER_BASE_ADDR + (HLS_SINGLE_FRAME_SIZE * i);
        self->vdmaFrameBufferBaseAddr_[i] = VDMA_FRAME_BUFFER_BASE_ADDR + (VDMA_SINGLE_FRAME_SIZE * i);
    }
    self->nextHlsWriteBufferIdx_ = 0; // 初始 HLS 写入缓冲区为 0
    self->currentDisplayBufferIdx_ = 0; // 初始显示缓冲区为 0

    xil_printf("--- VDMA Initialization (VdmaDisplay) ---\r\n");
    // 在SDT模式下，我们使用基地址查找配置，而不是设备ID
    xil_printf("  VDMA Base Address used for lookup: 0x%x\r\n", (unsigned int)XPAR_HDMI_OUTPUT_0_AXI_VDMA_0_BASEADDR);
    xil_printf("  VDMA Output Resolution (Locked): %u x %u\r\n", VDMA_OUTPUT_WIDTH, VDMA_OUTPUT_HEIGHT);
    xil_printf("  HLS Render Resolution (Configured): %u x %u\r\n", HLS_RENDER_WIDTH, HLS_RENDER_HEIGHT); // 打印HLS渲染分辨率
    xil_printf("  VDMA Expected Bytes per Pixel (BGR): %u\r\n", VDMA_BYTES_PER_PIXEL);
    xil_printf("  HLS IP Writes Bytes per Pixel (BGRX): %u\r\n", HLS_BYTES_PER_PIXEL);
    xil_printf("  VDMA Single Frame Buffer Size: %u bytes\r\n", VDMA_SINGLE_FRAME_SIZE);
    xil_printf("  HLS Single Frame Buffer Size: %u bytes\r\n", HLS_SINGLE_FRAME_SIZE);
    xil_printf("  Number of Frame Buffers (Triple Buffering): %u\r\n", VDMA_NUM_FRAME_BUFFERS);
#ifdef VDMA_DISPLAY_VERBOSE_INIT
    xil_printf("  HLS Frame Buffers (4Bpp) Start at: 0x%x\r\n", (unsigned int)HLS_FRAME_BUFFER_BASE_ADDR);
    for (i = 0; i < VDMA_NUM_FRAME_BUFFERS; ++i) {
        xil_printf("    HLS Frame Buffer %d Address: 0x%x\r\n", i, (unsigned int)self->hlsFrameBufferBaseAddr_[i]);
    }
    xil_printf("  VDMA Frame Buffers (3Bpp) Start at: 0x%x\r\n", (unsigned int)VDMA_FRAME_BUFFER_BASE_ADDR);
    for (i = 0; i < VDMA_NUM_FRAME_BUFFERS; ++i) {
        xil_printf("    VDMA Frame Buffer %d Address: 0x%x\r\n", i, (unsigned int)self->vdmaFrameBufferBaseAddr_[i]);
    }
#endif


    // 1. 查找 VDMA 设备配置 (使用基地址进行查找)
    // XPAR_AXIVDMA_0_BASEADDR 是SDT模式下VDMA实例的唯一标识符
    self->vdmaConfig_ = XAxiVdma_LookupConfig(XPAR_HDMI_OUTPUT_0_AXI_VDMA_0_BASEADDR);
    if (self->vdmaConfig_ == NULL) {
        xil_printf("Error: VDMA LookupConfig failed for Base Address 0x%x!\r\n", (unsigned int)XPAR_HDMI_OUTPUT_0_AXI_VDMA_0_BASEADDR);
        return XST_FAILURE;
    }
#ifdef VDMA_DISPLAY_VERBOSE_INIT
    xil_printf("  VDMA Config Found: BaseAddress=0x%x, MM2SStreamWidth=%d bits (from config structure)\r\n",
               (unsigned int)self->vdmaConfig_->BaseAddress, self->vdmaConfig_->Mm2SStreamWidth);
#endif
    // 确保 MM2SStreamWidth 是 24 位，与 VDMA_BYTES_PER_PIXEL=3 匹配
    if (self->vdmaConfig_->Mm2SStreamWidth != (VDMA_BYTES_PER_PIXEL * 8)) {
        xil_printf("ERROR: VDMA MM2S Stream Width from config (%d bits) does not match VDMA_BYTES_PER_PIXEL (%u * 8 = %u bits)!\r\n",
                   self->vdmaConfig_->Mm2SStreamWidth, VDMA_BYTES_PER_PIXEL, VDMA_BYTES_PER_PIXEL * 8);
        return XST_FAILURE; // 硬件配置不匹配，无法继续
    }


    // 2. 初始化 VDMA 驱动实例
    // CfgInitialize的第三个参数是VDMA控制寄存器的基地址，从查找到的配置中获取
    status = XAxiVdma_CfgInitialize(&self->vdmaInstance_, self->vdmaConfig_, self->vdmaConfig_->BaseAddress);
    if (status != XST_SUCCESS) {
        xil_printf("Error: VDMA CfgInitialize failed! Status=%d.\r\n", status);
        return status;
    }
    xil_printf("  VDMA driver instance initialized successfully.\r\n");

    // 3. 配置 VDMA MM2S (Read) 通道
    if (!self->vdmaConfig_->HasMm2S) {
        xil_printf("Error: VDMA hardware configuration does not include a Read (MM2S) channel.\r\n");
        return XST_FAILURE;
    }

    self->vdmaDmaSetup_.VertSizeInput = VDMA_OUTPUT_HEIGHT;
    self->vdmaDmaSetup_.HoriSizeInput = VDMA_OUTPUT_WIDTH * VDMA_BYTES_PER_PIXEL; // VDMA 期望 3 字节/像素
    self->vdmaDmaSetup_.Stride = VDMA_OUTPUT_WIDTH * VDMA_BYTES_PER_PIXEL;       // VDMA 期望 3 字节/像素
    self->vdmaDmaSetup_.FrameDelay = 0;
    self->vdmaDmaSetup_.EnableCircularBuf = 1; 
    self->vdmaDmaSetup_.EnableSync = 0;
    self->vdmaDmaSetup_.PointNum = 0;
    self->vdmaDmaSetup_.EnableFrameCounter = 0;
    self->vdmaDmaSetup_.FixedFrameStoreAddr = 0;
    self->vdmaDmaSetup_.GenLockRepeat = 0;
    self->vdmaDmaSetup_.EnableVFlip = 0;

    status = XAxiVdma_DmaConfig(&self->vdmaInstance_, XAXIVDMA_READ, &self->vdmaDmaSetup_);
    if (status != XST_SUCCESS) {
        xil_printf("Error: VDMA MM2S (Read) DmaConfig failed! Status=%d.\r\n", status);
        return status;
    }
    xil_printf("  VDMA MM2S (Read) channel configured successfully.\r\n");

    // 4. 设置 VDMA 帧缓冲区地址：VDMA 从 VDMA 专用的 3Bpp 缓冲区读取。
    status = XAxiVdma_DmaSetBufferAddr(&self->vdmaInstance_, XAXIVDMA_READ, self->vdmaFrameBufferBaseAddr_);
    if (status != XST_SUCCESS) {
        xil_printf("Error: VDMA MM2S (Read) DmaSetBufferAddr failed! Status=%d.\r\n", status);
        return status;
    }
    xil_printf("  VDMA MM2S (Read) channel %u VDMA-ready buffer addresses set successfully.\r\n", VDMA_NUM_FRAME_BUFFERS);

    // 5. 启动 VDMA MM2S 通道
    status = XAxiVdma_DmaStart(&self->vdmaInstance_, XAXIVDMA_READ);
    if (status != XST_SUCCESS) {
        xil_printf("Error: VDMA MM2S (Read) DmaStart failed! Status=%d.\r\n", status);
        return status;
    }
    xil_printf("  VDMA MM2S (Read) channel started successfully.\r\n");

    // 6. 清空所有 HLS 帧缓冲区为黑色 (0x00RRGGBB，即 0x00000000)
    for (i = 0; i < VDMA_NUM_FRAME_BUFFERS; ++i) {
        u32* hls_fb_ptr = (u32*)self->hlsFrameBufferBaseAddr_[i];
        for (int j = 0; j < (HLS_RENDER_WIDTH * HLS_RENDER_HEIGHT); ++j) { // 使用 HLS_RENDER_WIDTH/HEIGHT
            hls_fb_ptr[j] = 0x00000000; // 每个 32 位槽写入黑色
        }
        VdmaDisplay_flushCache(self->hlsFrameBufferBaseAddr_[i], HLS_SINGLE_FRAME_SIZE); // 刷新 HLS 缓冲区
    }
    xil_printf("  All HLS frame buffers cleared to black.\r\n");

    // 7. 清空所有 VDMA 帧缓冲区为黑色 (3 字节 BGR，即 0x000000)
    for (i = 0; i < VDMA_NUM_FRAME_BUFFERS; ++i) {
        memset((u8*)self->vdmaFrameBufferBaseAddr_[i], 0, VDMA_SINGLE_FRAME_SIZE);
        VdmaDisplay_flushCache(self->vdmaFrameBufferBaseAddr_[i], VDMA_SINGLE_FRAME_SIZE); // 刷新 VDMA 缓冲区
    }
    xil_printf("  All VDMA-ready frame buffers cleared to black.\r\n");


    // 8. 将 VDMA 停车（parking）到第一个 VDMA-ready 帧缓冲区 (黑色帧)。
    // 这将把 VDMA 显示初始化到帧缓冲区0，确保在渲染第一帧之前屏幕是黑色的。
    // 在这里，我们不需要在 StartParking 之前获取互斥量，因为这是初始化阶段。
    status = XAxiVdma_StartParking(&self->vdmaInstance_, 0, XAXIVDMA_READ);
    if (status != XST_SUCCESS) {
        xil_printf("Error: VDMA MM2S StartParking failed! Status=%d.\r\n", status);
        return status;
    }
    self->currentDisplayBufferIdx_ = 0; // 初始显示缓冲区为 0
    xil_printf("  VDMA MM2S (Read) channel parked to VDMA-ready buffer 0.\r\n");

    self->initialized_ = true;
    xil_printf("--- VDMA Initialization Complete (VdmaDisplay) ---\r\n");
    return XST_SUCCESS;
}

// 获取下一个可供 HLS/GPU 写入的帧缓冲区的索引
int VdmaDisplay_getNextHlsWriteBufferIdx(VdmaDisplay* self) {
    if (!self->initialized_) {
        return -1;
    }
    // 三缓冲逻辑：总是跳过当前正在显示 (currentDisplayBufferIdx_) 的缓冲区。
    // 在剩下的两个缓冲区中选择一个作为下一个写入目标。
    // 由于渲染任务已经通过信号量获得了渲染权限，
    // 这里只需提供一个“安全”的索引即可，即不等于 currentDisplayBufferIdx_ 的索引。
    // 这个函数返回的索引，只是简单地轮流选择下一个非当前显示缓冲区。
    int next_write_idx = (self->currentDisplayBufferIdx_ + 1) % VDMA_NUM_FRAME_BUFFERS;

    // 如果计算出的 next_write_idx 恰好是当前正在显示的缓冲区，则跳到再下一个。
    // 这种情况应该不会发生，因为我们总是跳过一个。
    if (next_write_idx == self->currentDisplayBufferIdx_) {
        next_write_idx = (next_write_idx + 1) % VDMA_NUM_FRAME_BUFFERS;
    }

    self->nextHlsWriteBufferIdx_ = next_write_idx; 
    return self->nextHlsWriteBufferIdx_;
}

// 获取特定索引的 HLS 帧缓冲区的地址
UINTPTR VdmaDisplay_getHlsFrameBufferAddr(const VdmaDisplay* self, int buffer_idx) {
    if (!self->initialized_) {
        return 0;
    }
    if (buffer_idx < 0 || buffer_idx >= VDMA_NUM_FRAME_BUFFERS) {
        return 0;
    }
    return self->hlsFrameBufferBaseAddr_[buffer_idx];
}

// 获取特定索引的 VDMA 帧缓冲区的地址
UINTPTR VdmaDisplay_getVdmaFrameBufferAddr(const VdmaDisplay* self, int buffer_idx) {
    if (!self->initialized_) {
        return 0;
    }
    if (buffer_idx < 0 || buffer_idx >= VDMA_NUM_FRAME_BUFFERS) {
        return 0;
    }
    return self->vdmaFrameBufferBaseAddr_[buffer_idx];
}


/**
 * @brief 执行从 HLS 渲染缓冲区到 VDMA 显示缓冲区的缩放、格式转换。
 *        此函数内部会刷新缓存，但不提交帧到 VDMA 显示，也不处理同步信号量。
 * @param self 指向 VdmaDisplay 实例的指针。
 * @param hls_buffer_idx HLS IP 写入完成的帧缓冲区的索引。
 * @return XST_SUCCESS 表示成功，其他值表示失败。
 */
int VdmaDisplay_processAndConvertFrame(VdmaDisplay* self, int hls_buffer_idx) {
    if (!self->initialized_) {
        return XST_FAILURE;
    }
    if (hls_buffer_idx < 0 || hls_buffer_idx >= VDMA_NUM_FRAME_BUFFERS) {
        return XST_FAILURE;
    }

    UINTPTR hls_framebuffer_addr = self->hlsFrameBufferBaseAddr_[hls_buffer_idx];
    UINTPTR vdma_framebuffer_addr = self->vdmaFrameBufferBaseAddr_[hls_buffer_idx];

    u32 hls_render_width = HLS_RENDER_WIDTH;
    u32 hls_render_height = HLS_RENDER_HEIGHT;
    u32 vdma_output_width = VDMA_OUTPUT_WIDTH;
    u32 vdma_output_height = VDMA_OUTPUT_HEIGHT;
    u32 vdma_single_frame_size = VDMA_SINGLE_FRAME_SIZE;

    if (hls_framebuffer_addr == 0 || vdma_framebuffer_addr == 0) {
        xil_printf("[VdmaDisplay]: ERROR: Invalid framebuffer address for index %d. Conversion aborted.\r\n", hls_buffer_idx);
        return XST_FAILURE;
    }

    // --- 确保 CPU 缓存失效，以便 PS 获取由 HLS IP 写入的最新像素数据 ---
    VdmaDisplay_invalidateCache(hls_framebuffer_addr, HLS_SINGLE_FRAME_SIZE);

    // ====================================================================================
    // HLS IP (320x240, 4Bpp BGRX) -> PS 缩放 + 格式转换 (640x480, 3Bpp BGR)
    // ====================================================================================
    u32* src_ptr_u32 = (u32*)hls_framebuffer_addr; // HLS 写入的 4Bpp BGRX, 320x240
    u8* dest_ptr_u8 = (u8*)vdma_framebuffer_addr;  // VDMA 期望的 3Bpp BGR, 640x480

    // 简单的最近邻上采样 (2x2 放大)
    for (u32 y = 0; y < vdma_output_height; ++y) {
        for (u32 x = 0; x < vdma_output_width; ++x) {
            // 计算源图像中的对应坐标
            // 640x480 是 320x240 的 2 倍
            u32 src_x = x / 2; 
            u32 src_y = y / 2;

            // 确保不超出源图像边界 (尽管理论上不会)
            if (src_x >= hls_render_width) src_x = hls_render_width - 1;
            if (src_y >= hls_render_height) src_y = hls_render_height - 1;

            u32 src_pixel_idx = src_y * hls_render_width + src_x;
            u32 pixel_bgrx = src_ptr_u32[src_pixel_idx]; // 读取一个 32 位的 BGRX 像素 (0x00RRGGBB)

            // 提取 B, G, R 分量
            u8 b = (u8)(pixel_bgrx & 0xFF);         // Blue
            u8 g = (u8)((pixel_bgrx >> 8) & 0xFF);  // Green
            u8 r = (u8)((pixel_bgrx >> 16) & 0xFF); // Red

            // 写入 3 字节 BGR 到 VDMA 目标缓冲区
            u32 dest_offset = (y * vdma_output_width + x) * 3;
            dest_ptr_u8[dest_offset + 0] = b;
            dest_ptr_u8[dest_offset + 1] = g;
            dest_ptr_u8[dest_offset + 2] = r;
        }
    }

    // 刷新 VDMA 目标缓冲区缓存，确保转换后的数据写入 DDR
    VdmaDisplay_flushCache(vdma_framebuffer_addr, vdma_single_frame_size);
    
    return XST_SUCCESS;
}

/**
 * @brief 将处理完成的 VDMA 就绪帧缓冲区提交给 VDMA 显示，并更新缓冲区状态。
 *        此函数负责获取互斥量，提交帧到 VDMA，并释放 xRenderingBufferAvailableSemaphore_ 信号量。
 * @param self 指向 VdmaDisplay 实例的指针。
 * @param buffer_idx 要提交给 VDMA 显示的 VDMA 就绪帧缓冲区的索引。
 * @return XST_SUCCESS 表示成功，其他值表示失败。
 */
int VdmaDisplay_presentFrameToVDMA(VdmaDisplay* self, int buffer_idx) {
    int status = XST_SUCCESS;

    if (!self->initialized_) {
        return XST_FAILURE;
    }
    if (buffer_idx < 0 || buffer_idx >= VDMA_NUM_FRAME_BUFFERS) {
        return XST_FAILURE;
    }

    // 1. 获取互斥量，确保 VDMA 提交操作的原子性
    if (xSemaphoreTake(self->xDisplayBufferCommitMutex_, portMAX_DELAY) != pdPASS) {
        xil_printf("Error: Failed to take xDisplayBufferCommitMutex_ in presentFrameToVDMA.\r\n");
        // 如果无法获取互斥量，表示严重问题
        // 这里不需要释放 xRenderingBufferAvailableSemaphore_，因为此函数是 VdmaDisplay_processAndConvertFrame 之后调用的。
        // 如果 `processAndConvertFrame` 成功，那么渲染任务已经消费了一个信号量。
        // 只有当 VDMA 提交失败时，才需要考虑如何处理这个已经渲染但无法显示的帧。
        return XST_FAILURE;
    }

    // 2. 通知 VDMA 在下一个垂直消隐期切换到指定帧缓冲区。
    status = XAxiVdma_StartParking(&self->vdmaInstance_, buffer_idx, XAXIVDMA_READ);
    if (status != XST_SUCCESS) {
        xil_printf("Error: VDMA MM2S StartParking failed with status %d for buffer %d.\r\n", status, buffer_idx);
        xSemaphoreGive(self->xDisplayBufferCommitMutex_); // 释放互斥量
        // 如果提交失败，我们应该释放一个信号量，以便渲染任务可以继续。
        // 因为这个帧虽然渲染了但无法显示。
        xSemaphoreGive(self->xRenderingBufferAvailableSemaphore_); 
        return status;
    }

    // 3. 更新当前正在显示的缓冲区索引
    self->currentDisplayBufferIdx_ = buffer_idx;

    // 4. 释放一个 xRenderingBufferAvailableSemaphore_ 信号量。
    // 这表示现在有一个旧的缓冲区已经从显示队列中“释放”出来，可以被渲染任务再次使用。
    if (xSemaphoreGive(self->xRenderingBufferAvailableSemaphore_) != pdPASS) {
        xil_printf("Error: Failed to give xRenderingBufferAvailableSemaphore_ in presentFrameToVDMA.\r\n");
        // 但仍然继续，因为Vdma提交成功了。
    }

    // 5. 释放互斥量
    xSemaphoreGive(self->xDisplayBufferCommitMutex_);

    return status;
}


u32 VdmaDisplay_getOutputWidth(const VdmaDisplay* self) {
    (void)self;
    return VDMA_OUTPUT_WIDTH;
}

u32 VdmaDisplay_getOutputHeight(const VdmaDisplay* self) {
    (void)self;
    return VDMA_OUTPUT_HEIGHT;
}

u32 VdmaDisplay_getHlsRenderWidth(const VdmaDisplay* self) {
    (void)self;
    return HLS_RENDER_WIDTH;
}

u32 VdmaDisplay_getHlsRenderHeight(const VdmaDisplay* self) {
    (void)self;
    return HLS_RENDER_HEIGHT;
}

u32 VdmaDisplay_getBytesPerPixel(const VdmaDisplay* self) {
    (void)self;
    return VDMA_BYTES_PER_PIXEL;
}

u32 VdmaDisplay_getHlsBytesPerPixel(const VdmaDisplay* self) {
    (void)self;
    return HLS_BYTES_PER_PIXEL;
}

u32 VdmaDisplay_getVdmaSingleFrameSize(const VdmaDisplay* self) {
    (void)self;
    return VDMA_SINGLE_FRAME_SIZE;
}

u32 VdmaDisplay_getHlsSingleFrameSize(const VdmaDisplay* self) {
    (void)self;
    return HLS_SINGLE_FRAME_SIZE;
}

// 获取当前显示缓冲区索引
int VdmaDisplay_getCurrentDisplayBufferIdx(const VdmaDisplay* self) {
    return self->currentDisplayBufferIdx_;
}

// 获取字体宽度
u32 VdmaDisplay_getFontWidth(const VdmaDisplay* self) {
    (void)self;
    return FONT_WIDTH;
}

// 获取字体高度
u32 VdmaDisplay_getFontHeight(const VdmaDisplay* self) {
    (void)self;
    return FONT_HEIGHT;
}

// 绘制单个字符
void VdmaDisplay_DrawChar(const VdmaDisplay* self, int buffer_idx, int x, int y, char character, u8 r, u8 g, u8 b) {
    if (!self->initialized_ || buffer_idx < 0 || buffer_idx >= VDMA_NUM_FRAME_BUFFERS) {
        return;
    }
    UINTPTR vdma_framebuffer_addr = self->vdmaFrameBufferBaseAddr_[buffer_idx];
    if (vdma_framebuffer_addr == 0) {
        return;
    }
    u8* dest_ptr_u8 = (u8*)vdma_framebuffer_addr;
    DrawChar(dest_ptr_u8, VDMA_OUTPUT_WIDTH, VDMA_OUTPUT_HEIGHT, x, y, character, r, g, b);
    // 刷新缓存以确保文本显示
    VdmaDisplay_flushCache(vdma_framebuffer_addr, VDMA_SINGLE_FRAME_SIZE);
}


// 绘制字符串
void VdmaDisplay_DrawString(const VdmaDisplay* self, int buffer_idx, int x, int y, const char* text, u8 r, u8 g, u8 b) {
    if (!self->initialized_ || buffer_idx < 0 || buffer_idx >= VDMA_NUM_FRAME_BUFFERS) {
        return;
    }
    UINTPTR vdma_framebuffer_addr = self->vdmaFrameBufferBaseAddr_[buffer_idx];
    if (vdma_framebuffer_addr == 0) {
        return;
    }
    u8* dest_ptr_u8 = (u8*)vdma_framebuffer_addr;
    DrawString(dest_ptr_u8, VDMA_OUTPUT_WIDTH, VDMA_OUTPUT_HEIGHT, x, y, text, r, g, b);
    // 刷新缓存以确保文本显示
    VdmaDisplay_flushCache(vdma_framebuffer_addr, VDMA_SINGLE_FRAME_SIZE);
}

// 绘制数字
void VdmaDisplay_DrawNumber(const VdmaDisplay* self, int buffer_idx, int x, int y, int number, u8 r, u8 g, u8 b) {
    if (!self->initialized_ || buffer_idx < 0 || buffer_idx >= VDMA_NUM_FRAME_BUFFERS) {
        return;
    }
    UINTPTR vdma_framebuffer_addr = self->vdmaFrameBufferBaseAddr_[buffer_idx];
    if (vdma_framebuffer_addr == 0) {
        return;
    }
    u8* dest_ptr_u8 = (u8*)vdma_framebuffer_addr;
    DrawNumber(dest_ptr_u8, VDMA_OUTPUT_WIDTH, VDMA_OUTPUT_HEIGHT, x, y, number, r, g, b);
    // 刷新缓存以确保文本显示
    VdmaDisplay_flushCache(vdma_framebuffer_addr, VDMA_SINGLE_FRAME_SIZE);
}
